import { IsInRect } from "../../../Matrix";
import { Coord } from "../../utils/Coord";
import { Room } from "../../utils/Room";

/** 获取最近的连接房间算法 */
export function ConnectClosestRooms(allRooms: Room[]) {
    const roomsCanLink = createTreeLinks(allRooms);

    //! 这个是最耗时的位置
    const result = getLinks(roomsCanLink);

    // ! 找到未连接的房间，并将连接数最多的房间和它们连接
    const second = getSingleRoomLink(allRooms);
    const result1 = getLinks(second);
    return [...result, ...result1];
}

/** 找到没有被连接的房间并和连接数最多的房间连接 */
function getSingleRoomLink(allRooms: Room[]) {
    const last = allRooms.filter((i) => i.connectedRooms.length === 0);
    const [biggest] = allRooms.sort((roomA, roomB) => {
        return roomB.tiles.length - roomA.tiles.length;
    });
    return last.map((item) => {
        return [biggest, item];
    }) as [Room, Room][];
}

/** 获取两个房间相互连接的点 */
function getLinks(roomsCanLink: [Room, Room][]) {
    const points = FindLinkPoint(roomsCanLink);
    return points.map(([roomA, roomB, tileA, tileB]) => {
        Room.ConnectRooms(roomA, roomB);
        return [tileA, tileB];
    });
}

/**  找出每个房间最近的房间的链接 */
function createTreeLinks(allRooms: Room[]): [Room, Room][] {
    let collection: [Room, Room][] = [];
    const length = allRooms.length;
    /** 遍历每个房间，并向后查找最短路径 */
    for (let index = 0; index < length; index++) {
        const roomA = allRooms[index];
        let shortest = Infinity;
        let closest: Room;
        // 只找后面的对象是否能够链接
        for (let index1 = index + 1; index1 < length; index1++) {
            const roomB = allRooms[index1];
            if (roomB) {
                const long = calcDistance(roomA.center, roomB.center);
                if (long < shortest) {
                    shortest = long;
                    closest = roomB;
                }
            }
        }

        //! 有可能尾部的房间已经被连接完了
        if (closest!) {
            collection.push([roomA, closest!]);
        }
    }
    return collection;
}

function calcDistance(tileA: Coord, tileB: Coord) {
    //! 不需要进行开方
    return (
        Math.pow(tileA.tileX - tileB.tileX, 2) +
        Math.pow(tileA.tileY - tileB.tileY, 2)
    );
}

/** 找到两个房间的最短连接的端点 */
function FindLinkPoint(
    treeLinks: [Room, Room][]
): Array<[Room, Room, Coord, Coord]> {
    return treeLinks.flatMap(([roomA, roomB]) => {
        let distance = Infinity;
        let result: [Coord, Coord];
        const rect = getRect(roomA, roomB);
        const APart = roomA.edgeTiles.filter((i) => {
            return IsInRect(i.tileX, i.tileY, rect);
        });
        const BPart = roomB.edgeTiles.filter((i) => {
            return IsInRect(i.tileX, i.tileY, rect);
        });
        APart.forEach((tileA) => {
            BPart.forEach((tileB) => {
                let long = calcDistance(tileA, tileB);
                if (long < distance) {
                    distance = long;
                    result = [tileA, tileB];
                }
            });
        });
        // console.log(result!);
        if (result!) {
            return [[roomA, roomB, ...result!]];
        } else {
            return [];
        }
    });
}
function getRect(roomA: Room, roomB: Room) {
    const ACenter = roomA.center;
    const BCenter = roomB.center;

    const [minX, maxX] =
        ACenter.tileX > BCenter.tileX
            ? [BCenter.tileX, ACenter.tileX]
            : [ACenter.tileX, BCenter.tileX];
    const [minY, maxY] =
        ACenter.tileY > BCenter.tileY
            ? [BCenter.tileY, ACenter.tileY]
            : [ACenter.tileY, BCenter.tileY];
    const rect = { minX, maxX, minY, maxY };
    return rect;
}
